/*
 * jQuery esMobile
 * by Esmool 2015
 *
 */
(function ($) {

	/*** global methods ***/

	/**
	 * global element
	 */
	$.esPage = {

		// page/dialog context stack
		pageStack: [],

		// current selector, options and queryParams
		selector: null,
		options: null,
		queryParams: null,

		// dialog context flag
		isDialogView: false,

		// swap page style, type int, default 0, indicate the render effort of the swapment, with values:
		// 0		direct hide and show
		// 1		move in from right (Not support yet)
		// 2		flip in from right (Not support yet)
		// 3		smoothly transform in (Not support yet)
		// ...		others (Not support yet)
		swapStyles: 0
	};

	/**
	 * move to new page, with optional parameter %{options}
	 *
	 * %{options}		configurate the dialog activity, with fields:
	 *		isSelector		boolean, default false, indicates whether the first parameter %{selector} is really a selector, or a set of html
	 *		width			string/int, default 100%, indicates the total width of the dialog
	 *		height			string/int, default 100%, indicates the total height of the dialog
	 *		queryParams		object, default {}, set the parameters need transfer, those will be accessable via %{$.esPage.queryParams}
	 *
	 * WARNING: this method CAN NOT be used under the context of a dialog
	 */
	$.esPage.moveTo = function(selector, options) {
		var obj = $.esPage;

		if (obj.isDialogView) {
			console.warn('Invalid operation: invoking $.esPage.moveTo() during a dialog context life time. No action performed.');
			return;
		}

		var oldSelector = obj.selector;
		var oldOptions = obj.options;

		if (oldSelector) {
			obj.pageStack.push({
				selector: obj.selector,
				options: obj.options,
				queryParams: obj.queryParams,
				isDialogView: obj.isDialogView
			});
		}

		obj.options = $(selector).esPage(options);
		obj.selector = selector;
		obj.queryParams = obj.options.queryParams;
		obj.isDialogView = false;

		swapPage(oldSelector, selector, $.esPage.swapStyle);
	};

	/**
	 * move to last navigation page, without parameter transfermation
	 *
	 * NOTICE: DO NOT use method pair %{$.esPage.moveTo} and %{$.esPage.back} to perform dialog action
	 *			use %{$.esPage.showDialog} instead.
	 *
	 *	WARNING: this method CAN NOT be used under the context of a dialog
	 */
	$.esPage.back = function() {
		var obj = $.esPage;

		if (obj.isDialogView) {
			console.warn('Invalid operation: invoking $.esPage.back() during a dialog context life time. No action performed.');
			return;
		}

		var newObj = obj.pageStack.pop();
		if (!newObj)
			return;

		var newSelector = newObj.selector;
		var newOptions = newObj.options;
		var newQueryParams = newObj.queryParams;
		var newIsDialogView = newObj.isDialogView;

		swapPage(obj.selector, newSelector, $.esPage.swapStyle);

		obj.selector = newSelector;
		obj.options = newOptions;
		obj.queryParams = newQueryParams;
		obj.isDialogView = newIsDialogView;
	};

	/**
	 * show dialog with spectific selector/content, with parameter %{options}
	 *
	 * %{options}		configurate the dialog activity, with fields:
	 *		isSelector		boolean, default false, indicates whether the first parameter %{selector} is really a selector, or a set of html
	 *		width			string/int, default 100%, indicates the total width of the dialog
	 *		height			string/int, default 100%, indicates the total height of the dialog
	 *		modal			boolean, default true, indicates whether the dialog will mask the content below it
	 *		queryParams		object, default {}, set the parameters need transfer, those will be accessable via %{$.esPage.queryParams}
	 *		callback		function(cancelled, data), default null, the callback function that while dialog closed(fired with %{$.esPage.closeDialog}, 	manually)
	 *
	 *	%{options} provides other configuration fields accroding to %{$.fn.esPage} as well, those duplicated fields with the same name are overrided by new meanings up in the list.
	 *
	 * WARNING: this pair of methods, %{$.esPage.showDialog} and %{$.esPage.closeDialog}, impliemented the IUID principle (Immediately Use & Immediately Destroy). There would be no state information remained after invoking %{$.esPage.closeDialog}. If want to presurve page state in further usage, use method pair %{$.esPage.moveTo} and %{$.esPage.back} instead.
	 */
	$.esPage.showDialog = function(selector, options) {
		var obj = $.esPage;

		var oldSelector = obj.selector;
		var oldOptions = obj.options;

		if (oldSelector) {
			obj.pageStack.push({
				selector: obj.selector,
				options: obj.options,
				queryParams: obj.queryParams,
				isDialogView: obj.isDialogView
			});
		}

		if (!options)
			options = {};

		// TODO: for specific width/height configuration, and modal options, implementation needed here

		obj.options = $(selector).esPage(options);
		obj.selector = selector;
		obj.queryParams = $.extend({}, obj.options.queryParams, options.queryParams);
		obj.isDialogView = true;

		swapPage(oldSelector, selector, $.esPage.swapStyle);
	};

	/**
	 * close current dialog and go back to the last context, with parameter %{cancelled} and optional parameter %{data}
	 *
	 *	%{cancelled}	boolean, notify the invoking context that currently closing dialog is triggled by cancel event or not
	 *	%{data}			object, optional, default null, data need transfer to invoking context
	 *
	 * WARNING: this method CAN NOT be used under the context of a page
	 */
	$.esPage.closeDialog = function(cancelled, data) {
		var obj = $.esPage;

		if (!obj.isDialogView) {
			console.warn('Invalid operation: invoking $.esPage.closeDialog() during a page context life time. No action performed.');
			return;
		}

		var newObj = obj.pageStack.pop();
		if (!newObj)
			return;

		var newSelector = newObj.selector;
		var newOptions = newObj.options;
		var newQueryParams = newObj.queryParams;
		var newIsDialogView = newObj.isDialogView;
		var callback = (obj.options && obj.options.callback ? obj.options.callback : null);

		swapPage(obj.selector, newSelector, $.esPage.swapStyle);

		obj.selector = newSelector;
		obj.options = newOptions;
		obj.queryParams = newQueryParams;
		obj.isDialogView = newIsDialogView;

		if (callback)
			callback(cancelled, data);
	};

	/*** internal methods ***/

	/**
	 * swap page with different effort
	 *
	 * style	int, default 0, indicate the render effort of the swapment, with values:
	 *		0		direct hide and show
	 *		1		move in from right (Not support yet)
	 *		2		flip in from right (Not support yet)
	 *		3		smoothly transform in (Not support yet)
	 *		...		others (Not support yet)
	 */
	var swapPage = function(from, to, style) {
		// FURTHER WORK: need implement some animations page swithing efforts here
		var sty = style || 0;
		if (sty != 0)
			console.warn('$.esPage.swapStyle currently only support value 0, nonzero value ignored.');

		$(from).esPage('hide');
		$(to).esPage('show');
	};

	/*** instance methods ***/

	$.fn.esPage = function (options, params) {
		if (typeof options == 'string')
            return $.esPage.methods[options](this, params);

        var opts = $.extend({}, $.esPage.options, options);
		$(this).each(function () {
			var me = $(this).css('display', 'none');
		});

		return opts;
	};

	/**
	* default methods
	*/
	$.esPage.methods = {

		show: function (selector) {
			$(selector).css('display', 'block');
		},

		hide: function (selector) {
			$(selector).css('display', 'none');
		},

	};

	/**
	 * default options
	 */
	$.esPage.options = {
		isSelector		: false, 	// boolean, default false, indicates whether the first parameter %{selector} is really a selector, or a set of html
		width			: '100%',	// string/int, default 100%, indicates the total width of the dialog
		height			: '100%',	// string/int, default 100%, indicates the total height of the dialog
		modal			: true, 	// boolean, default true, indicates whether the dialog will mask the content below it
		queryParams		: {},		// object, default {}, set the parameters need transfer, those will be accessable via %{$.esPage.queryParams}
		callback		: null,		// function(cancelled, data), default null, the callback function that while dialog closed(fired with %{$.esPage.closeDialog}, 	manually)
	};

})(jQuery);